package com.flowable.modules.rest.utils;

import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CreateChildShape {

    /**
     * 简单自定义工作流组成可分为 1个 startEvent，1个 finishEvent，1个 endEvent,
     * 当step(n)(n>=1)时的 startFlowSequence,finishFlowSequence
     * 每个step对应的userTask 记为 userTaskStep_n
     * 每个step与endEvent连接的endFlowSequence 记为 endFlowSequence_n
     * step之间连接的taskFlowSequence 记为 taskFlowSequence_n-(n-1)
     * <p>
     * 基于如此设计，开始组装shape
     */

    public static Map<String,Object> createStartEvent() {
        Map<String,Object> childShape = new HashMap();

        //resourceId
        childShape.put("resourceId", "startEvent");
        //properties
        Map<String,Object> childShapeProperties = new HashMap();
        childShapeProperties.put("overrideid", "start");
        childShapeProperties.put("name", "开始");
        childShapeProperties.put("documentation", "");
        childShapeProperties.put("executionlisteners", "");
        childShapeProperties.put("initiator", "");
        childShapeProperties.put("formkeydefinition", "");
        childShapeProperties.put("formreference", "");
        childShapeProperties.put("formfieldvalidation", true);
        childShapeProperties.put("formproperties", "");
        childShape.put("properties", childShapeProperties);
        //stencil
        Map<String,Object> childShapeStencil = new HashMap();
        /* 与之相关联的指针对象resourceId */
        childShapeStencil.put("id", "StartNoneEvent");
        childShape.put("stencil", childShapeStencil);
        //childShapes
        childShape.put("childShapes", new ArrayList<>());
        //outgoing
        List childShapeOutgoings = new ArrayList();
        Map<String,Object> childShapeOutgoing1 = new HashMap();
        childShapeOutgoing1.put("resourceId","startFlowSequence");
        childShapeOutgoings.add(childShapeOutgoing1);
        childShape.put("outgoing", childShapeOutgoings);
        //bounds
        Map<String,Object> childShapeBounds = new HashMap();
        Map<String,Object> childShapeBoundsLowerRight = new HashMap();
        childShapeBoundsLowerRight.put("x", 130);
        childShapeBoundsLowerRight.put("y", 190);
        childShapeBounds.put("lowerRight", childShapeBoundsLowerRight);
        Map<String,Object> childShapeBoundsUpperLeft = new HashMap();
        childShapeBoundsUpperLeft.put("x", 100);
        childShapeBoundsUpperLeft.put("y", 160);
        childShapeBounds.put("upperLeft", childShapeBoundsUpperLeft);
        childShape.put("bounds", childShapeBounds);
        //dockers
        childShape.put("dockers", new ArrayList<>());

        return childShape;
    }

    public static Map<String,Object> createFinishEvent(int stepNum) {
        Map<String,Object> childShape = new HashMap();

        //resourceId
        childShape.put("resourceId", "finishEvent");
        //properties
        Map<String,Object> childShapeProperties = new HashMap();
        childShapeProperties.put("overrideid", "finish");
        childShapeProperties.put("name", "完成");
        childShapeProperties.put("documentation", "");
        childShapeProperties.put("executionlisteners", "");
        childShape.put("properties", childShapeProperties);
        //stencil
        Map<String,Object> childShapeStencil = new HashMap();
        /* 与之相关联的指针对象resourceId */
        childShapeStencil.put("id", "EndNoneEvent");
        childShape.put("stencil", childShapeStencil);
        //childShapes
        childShape.put("childShapes", new ArrayList<>());
        //outgoing
        childShape.put("outgoing", new ArrayList());
        //bounds
        Map<String,Object> childShapeBounds = new HashMap();
        Map<String,Object> childShapeBoundsLowerRight = new HashMap();
        childShapeBoundsLowerRight.put("x", 130+(stepNum+1)*50+stepNum*100);
        childShapeBoundsLowerRight.put("y", 190);
        childShapeBounds.put("lowerRight", childShapeBoundsLowerRight);
        Map<String,Object> childShapeBoundsUpperLeft = new HashMap();
        childShapeBoundsUpperLeft.put("x", 100+(stepNum+1)*50+stepNum*100);
        childShapeBoundsUpperLeft.put("y", 160);
        childShapeBounds.put("upperLeft", childShapeBoundsUpperLeft);
        childShape.put("bounds", childShapeBounds);
        //dockers
        childShape.put("dockers", new ArrayList<>());

        return childShape;
    }

    public static Map<String,Object> createEndEvent(int stepNum) {
        Map<String,Object> childShape = new HashMap();

        //resourceId
        childShape.put("resourceId", "endEvent");
        //properties
        Map<String,Object> childShapeProperties = new HashMap();
        childShapeProperties.put("overrideid", "end");
        childShapeProperties.put("name", "结束");
        childShapeProperties.put("documentation", "");
        childShapeProperties.put("executionlisteners", "");
        childShapeProperties.put("terminateall", "false");
        childShape.put("properties", childShapeProperties);
        //stencil
        Map<String,Object> childShapeStencil = new HashMap();
        /* 与之相关联的指针对象resourceId */
        childShapeStencil.put("id", "EndTerminateEvent");
        childShape.put("stencil", childShapeStencil);
        //childShapes
        childShape.put("childShapes", new ArrayList<>());
        //outgoing
        childShape.put("outgoing", new ArrayList());
        //bounds
        Map<String,Object> childShapeBounds = new HashMap();
        Map<String,Object> childShapeBoundsLowerRight = new HashMap();
        childShapeBoundsLowerRight.put("x", 130);
        childShapeBoundsLowerRight.put("y", 290);
        childShapeBounds.put("lowerRight", childShapeBoundsLowerRight);
        Map<String,Object> childShapeBoundsUpperLeft = new HashMap();
        childShapeBoundsUpperLeft.put("x", 100);
        childShapeBoundsUpperLeft.put("y", 260);
        childShapeBounds.put("upperLeft", childShapeBoundsUpperLeft);
        childShape.put("bounds", childShapeBounds);
        //dockers
        childShape.put("dockers", new ArrayList<>());

        return childShape;
    }

    public static Map<String,Object> createStartFlowSequence() {
        Map<String,Object> childShape = new HashMap();

        //resourceId
        childShape.put("resourceId", "startFlowSequence");
        //properties
        Map<String,Object> childShapeProperties = new HashMap();
        childShapeProperties.put("overrideid", "startFlowSequence");
        childShapeProperties.put("name", "发起");
        childShapeProperties.put("documentation", "");
        Map<String,Object> conditionsequenceflow = new HashMap();
        Map<String,Object> expression = new HashMap();
        expression.put("type", "static");
        expression.put("staticValue", "");
        conditionsequenceflow.put("expression", expression);
        childShapeProperties.put("conditionsequenceflow", conditionsequenceflow);
        childShapeProperties.put("executionlisteners", "");
        childShapeProperties.put("defaultflow", "false");
        childShapeProperties.put("skipexpression", "");
        childShape.put("properties", childShapeProperties);
        //stencil
        Map<String,Object> childShapeStencil = new HashMap();
        /* 与之相关联的指针对象resourceId */
        childShapeStencil.put("id", "SequenceFlow");
        childShape.put("stencil", childShapeStencil);
        //childShapes
        childShape.put("childShapes", new ArrayList<>());
        //outgoing
        List childShapeOutgoings = new ArrayList();
        Map<String,Object> childShapeOutgoing1 = new HashMap();
        childShapeOutgoing1.put("resourceId", "userTaskStep_1");
        childShapeOutgoings.add(childShapeOutgoing1);
        childShape.put("outgoing", childShapeOutgoings);
        //bounds
        Map<String,Object> childShapeBounds = new HashMap();
        Map<String,Object> childShapeBoundsLowerRight = new HashMap();
        childShapeBoundsLowerRight.put("x", 179.635);
        childShapeBoundsLowerRight.put("y", 175);
        childShapeBounds.put("lowerRight", childShapeBoundsLowerRight);
        Map<String,Object> childShapeBoundsUpperLeft = new HashMap();
        childShapeBoundsUpperLeft.put("x", 130.375);
        childShapeBoundsUpperLeft.put("y", 175);
        childShapeBounds.put("upperLeft", childShapeBoundsUpperLeft);
        childShape.put("bounds", childShapeBounds);
        //dockers
        List childShapeDockers = new ArrayList();
        Map<String,Object> childShapeDocker1 = new HashMap();
        childShapeDocker1.put("x", 15);
        childShapeDocker1.put("y", 15);
        childShapeDockers.add(childShapeDocker1);
        Map<String,Object> childShapeDocker2 = new HashMap();
        childShapeDocker2.put("x", 50);
        childShapeDocker2.put("y", 40);
        childShapeDockers.add(childShapeDocker2);
        childShape.put("dockers", childShapeDockers);
        //target
        Map<String,Object> target = new HashMap();
        target.put("resourceId", "userTaskStep_1");
        childShape.put("target", target);

        return childShape;
    }

    public static Map<String,Object> createFinishFlowSequence(int stepNum) {
        Map<String,Object> childShape = new HashMap();

        //resourceId
        childShape.put("resourceId", "finishFlowSequence");
        //properties
        Map<String,Object> childShapeProperties = new HashMap();
        childShapeProperties.put("overrideid", "finishFlowSequence");
        childShapeProperties.put("name", "办结");
        childShapeProperties.put("documentation", "");
        Map<String,Object> conditionsequenceflow = new HashMap();
        Map<String,Object> expression = new HashMap();
        expression.put("type", "static");

        expression.put("staticValue", "");
        conditionsequenceflow.put("expression", expression);
        childShapeProperties.put("conditionsequenceflow", conditionsequenceflow);
        childShapeProperties.put("executionlisteners", "");
        childShapeProperties.put("defaultflow", "false");
        childShapeProperties.put("skipexpression", "");
        childShape.put("properties", childShapeProperties);
        //stencil
        Map<String,Object> childShapeStencil = new HashMap();
        /* 与之相关联的指针对象resourceId */
        childShapeStencil.put("id", "SequenceFlow");
        childShape.put("stencil", childShapeStencil);
        //childShapes
        childShape.put("childShapes", new ArrayList<>());
        //outgoing
        List childShapeOutgoings = new ArrayList();
        Map<String,Object> childShapeOutgoing1 = new HashMap();
        childShapeOutgoing1.put("resourceId", "finishEvent");
        childShapeOutgoings.add(childShapeOutgoing1);
        childShape.put("outgoing", childShapeOutgoings);
        //bounds
        Map<String,Object> childShapeBounds = new HashMap();
        Map<String,Object> childShapeBoundsLowerRight = new HashMap();
        childShapeBoundsLowerRight.put("x", 130+stepNum*50+stepNum*100+0.375);
        childShapeBoundsLowerRight.put("y", 175);
        childShapeBounds.put("lowerRight", childShapeBoundsLowerRight);
        Map<String,Object> childShapeBoundsUpperLeft = new HashMap();
        childShapeBoundsUpperLeft.put("x", 130+(stepNum+1)*50+stepNum*100-0.375);
        childShapeBoundsUpperLeft.put("y", 175);
        childShapeBounds.put("upperLeft", childShapeBoundsUpperLeft);
        childShape.put("bounds", childShapeBounds);
        //dockers
        List childShapeDockers = new ArrayList();
        Map<String,Object> childShapeDocker1 = new HashMap();
        childShapeDocker1.put("x", 50);
        childShapeDocker1.put("y", 40);
        childShapeDockers.add(childShapeDocker1);
        Map<String,Object> childShapeDocker2 = new HashMap();
        childShapeDocker2.put("x", 14);
        childShapeDocker2.put("y", 14);
        childShapeDockers.add(childShapeDocker2);
        childShape.put("dockers", childShapeDockers);
        //target
        Map<String,Object> target = new HashMap();
        target.put("resourceId", "finishEvent");
        childShape.put("target", target);

        return childShape;
    }

    public static Map<String,Object> createUserTask(int stepNum, String stepName, boolean isLastStep, List<String> groups, List<String> users,boolean isCountSign,boolean isScheduled) {
        Map<String,Object> childShape = new HashMap();

        //resourceId
        childShape.put("resourceId", "userTaskStep_" + stepNum);
        //properties
        Map<String,Object> childShapeProperties = new HashMap();
        childShapeProperties.put("overrideid", "userTaskStep_" + stepNum);
        childShapeProperties.put("name", stepName);
        childShapeProperties.put("documentation", "");
        childShapeProperties.put("asynchronousdefinition", "false");
        if(isCountSign){
            childShapeProperties.put("exclusivedefinition", "true");
        } else {
            childShapeProperties.put("exclusivedefinition", "false");
        }
        childShapeProperties.put("executionlisteners", "");
        if(isCountSign){
            childShapeProperties.put("multiinstance_type", "Parallel");
        } else {
            childShapeProperties.put("multiinstance_type", "None");
        }
        childShapeProperties.put("multiinstance_cardinality", "");
        if(isCountSign){
            childShapeProperties.put("multiinstance_collection", "${multiInstanceHandler.getList(execution)}");
        } else {
            childShapeProperties.put("multiinstance_collection", "");
        }
        if(isCountSign){
            childShapeProperties.put("multiinstance_variable", "signUser");
        } else {
            childShapeProperties.put("multiinstance_variable", "");
        }
        if(isCountSign){
            childShapeProperties.put("multiinstance_condition", "${multiInstanceHandler.getComplete(execution)}");
        } else {
            childShapeProperties.put("multiinstance_condition", "");
        }

        childShapeProperties.put("isforcompensation", "false");
        /* 传入user和role参数 */
        Map<String,Object> usertaskassignment = new HashMap();
        Map<String,Object> assignment = new HashMap();
        assignment.put("type", "static");
        if(stepNum == 1) {
            assignment.put("assignee","${userId}");
        } else {
            if(!CollectionUtils.isEmpty(groups)) {
                List candidateGroups = new ArrayList();
                for (String group : groups) {
                    Map<String,Object> candidateGroup = new HashMap();
                    candidateGroup.put("value", group);
                    candidateGroups.add(candidateGroup);
                }
                assignment.put("candidateGroups", candidateGroups);
            }
            if(!CollectionUtils.isEmpty(users)) {
                List candidateUsers = new ArrayList();
                for (String user : users) {
                    Map<String,Object> candidateUser = new HashMap();
                    candidateUser.put("value", user);
                    candidateUsers.add(candidateUser);
                }
                assignment.put("candidateUsers", candidateUsers);
            }
        }
        usertaskassignment.put("assignment", assignment);
        childShapeProperties.put("usertaskassignment", usertaskassignment);
        childShapeProperties.put("formkeydefinition", "");
        childShapeProperties.put("formreference", "");
        childShapeProperties.put("formfieldvalidation", true);
        //存放调度标识
        if(isScheduled){
            childShapeProperties.put("duedatedefinition", "1");
        } else {
            childShapeProperties.put("duedatedefinition", "");
        }
        childShapeProperties.put("prioritydefinition", "");
        childShapeProperties.put("formproperties", "");
        childShapeProperties.put("tasklisteners", "");
        childShapeProperties.put("skipexpression", "");
        childShapeProperties.put("categorydefinition", "");
        childShape.put("properties", childShapeProperties);
        //stencil
        Map<String,Object> childShapeStencil = new HashMap();
        childShapeStencil.put("id", "UserTask");
        childShape.put("stencil", childShapeStencil);
        //childShapes
        childShape.put("childShapes", new ArrayList<>());
        //outgoing
        /* 与之相关联的指针对象resourceId */
        List childShapeOutgoings = new ArrayList();
        Map<String,Object> childShapeOutgoing1 = new HashMap();
        /* 非最后一步时为下一步指针
         *  为最后一步时为办结指针 */
        if (isLastStep) {
            childShapeOutgoing1.put("resourceId", "finishFlowSequence");
        } else {
            childShapeOutgoing1.put("resourceId", "taskFlowSequence_" + stepNum + "-" + (stepNum + 1));
        }
        childShapeOutgoings.add(childShapeOutgoing1);
        Map<String,Object> childShapeOutgoing2 = new HashMap();
        childShapeOutgoing2.put("resourceId", "endFlowSequence_" + stepNum);
        childShapeOutgoings.add(childShapeOutgoing2);
        childShape.put("outgoing", childShapeOutgoings);
        //bounds
        Map<String,Object> childShapeBounds = new HashMap();
        Map<String,Object> childShapeBoundsLowerRight = new HashMap();
        childShapeBoundsLowerRight.put("x", 230+stepNum*50+(stepNum-1)*100);
        childShapeBoundsLowerRight.put("y", 215);
        childShapeBounds.put("lowerRight", childShapeBoundsLowerRight);
        Map<String,Object> childShapeBoundsUpperLeft = new HashMap();
        childShapeBoundsUpperLeft.put("x", 130+stepNum*50+(stepNum-1)*100);
        childShapeBoundsUpperLeft.put("y", 135);
        childShapeBounds.put("upperLeft", childShapeBoundsUpperLeft);
        childShape.put("bounds", childShapeBounds);
        //dockers
        childShape.put("dockers", new ArrayList());

        return childShape;
    }

    public static Map<String,Object> createEndFlowSequence(int stepNum) {
        Map<String,Object> childShape = new HashMap();

        //resourceId
        childShape.put("resourceId", "endFlowSequence_" + stepNum);
        //properties
        Map<String,Object> childShapeProperties = new HashMap();
        childShapeProperties.put("overrideid", "endFlowSequence_" + stepNum);
        childShapeProperties.put("name", "不通过");
        childShapeProperties.put("documentation", "");
        Map<String,Object> conditionsequenceflow = new HashMap();
        Map<String,Object> expression = new HashMap();
        expression.put("type", "static");
        expression.put("staticValue", "${flag==2}");
        conditionsequenceflow.put("expression", expression);
        childShapeProperties.put("conditionsequenceflow", conditionsequenceflow);
        childShapeProperties.put("executionlisteners", "");
        childShapeProperties.put("defaultflow", "false");
        childShapeProperties.put("skipexpression", "");
        childShape.put("properties", childShapeProperties);
        //stencil
        Map<String,Object> childShapeStencil = new HashMap();
        /* 与之相关联的指针对象resourceId */
        childShapeStencil.put("id", "SequenceFlow");
        childShape.put("stencil", childShapeStencil);
        //childShapes
        childShape.put("childShapes", new ArrayList<>());
        //outgoing
        List childShapeOutgoings = new ArrayList();
        Map<String,Object> childShapeOutgoing1 = new HashMap();
        childShapeOutgoing1.put("resourceId", "endEvent");
        childShapeOutgoings.add(childShapeOutgoing1);
        childShape.put("outgoing", childShapeOutgoings);
        //bounds
        Map<String,Object> childShapeBounds = new HashMap();
        Map<String,Object> childShapeBoundsLowerRight = new HashMap();
        childShapeBoundsLowerRight.put("x", 130+stepNum*150-50-0.375);
        childShapeBoundsLowerRight.put("y", 135);
        childShapeBounds.put("lowerRight", childShapeBoundsLowerRight);
        Map<String,Object> childShapeBoundsUpperLeft = new HashMap();
        childShapeBoundsUpperLeft.put("x", 130+0.375);
        childShapeBoundsUpperLeft.put("y", 275);
        childShapeBounds.put("upperLeft", childShapeBoundsUpperLeft);
        childShape.put("bounds", childShapeBounds);
        //dockers
        List childShapeDockers = new ArrayList();
        Map<String,Object> childShapeDocker1 = new HashMap();
        childShapeDocker1.put("x", 50);
        childShapeDocker1.put("y", 40);
        childShapeDockers.add(childShapeDocker1);
        Map<String,Object> childShapeDocker2 = new HashMap();
        childShapeDocker2.put("x", 14);
        childShapeDocker2.put("y", 14);
        childShapeDockers.add(childShapeDocker2);
        childShape.put("dockers", childShapeDockers);
        //target
        Map<String,Object> target = new HashMap();
        target.put("resourceId", "endEvent");
        childShape.put("target", target);

        return childShape;
    }

    public static Map<String,Object> createTaskFlowSequence(int stepNum) {
        if (stepNum > 1) {
            Map<String,Object> childShape = new HashMap();

            //resourceId
            childShape.put("resourceId", "taskFlowSequence_" + (stepNum - 1) + "-" + stepNum);
            //properties
            Map<String,Object> childShapeProperties = new HashMap();
            childShapeProperties.put("overrideid", "taskFlowSequence_" + (stepNum - 1) + "-" + stepNum);
            childShapeProperties.put("name", "通过");
            childShapeProperties.put("documentation", "");
            Map<String,Object> conditionsequenceflow = new HashMap();
            Map<String,Object> expression = new HashMap();
            expression.put("type", "static");
            expression.put("staticValue", "${flag==1}");
            conditionsequenceflow.put("expression", expression);
            childShapeProperties.put("conditionsequenceflow", conditionsequenceflow);
            childShapeProperties.put("executionlisteners", "");
            childShapeProperties.put("defaultflow", "false");
            childShapeProperties.put("skipexpression", "");
            childShape.put("properties", childShapeProperties);
            //stencil
            Map<String,Object> childShapeStencil = new HashMap();
            /* 与之相关联的指针对象resourceId */
            childShapeStencil.put("id", "SequenceFlow");
            childShape.put("stencil", childShapeStencil);
            //childShapes
            childShape.put("childShapes", new ArrayList<>());
            //outgoing
            List childShapeOutgoings = new ArrayList();
            Map<String,Object> childShapeOutgoing1 = new HashMap();
            childShapeOutgoing1.put("resourceId", "userTaskStep_" + stepNum);
            childShapeOutgoings.add(childShapeOutgoing1);
            childShape.put("outgoing", childShapeOutgoings);
            //bounds
            Map<String,Object> childShapeBounds = new HashMap();
            Map<String,Object> childShapeBoundsLowerRight = new HashMap();
            childShapeBoundsLowerRight.put("x", 130+150*stepNum+50-0.375);
            childShapeBoundsLowerRight.put("y", 175);
            childShapeBounds.put("lowerRight", childShapeBoundsLowerRight);
            Map<String,Object> childShapeBoundsUpperLeft = new HashMap();
            childShapeBoundsUpperLeft.put("x", 130+150*stepNum+0.375);
            childShapeBoundsUpperLeft.put("y", 175);
            childShapeBounds.put("upperLeft", childShapeBoundsUpperLeft);
            childShape.put("bounds", childShapeBounds);
            //dockers
            List childShapeDockers = new ArrayList();
            Map<String,Object> childShapeDocker1 = new HashMap();
            childShapeDocker1.put("x", 50);
            childShapeDocker1.put("y", 40);
            childShapeDockers.add(childShapeDocker1);
            Map<String,Object> childShapeDocker2 = new HashMap();
            childShapeDocker2.put("x", 50);
            childShapeDocker2.put("y", 40);
            childShapeDockers.add(childShapeDocker2);
            childShape.put("dockers", childShapeDockers);
            //target
            Map<String,Object> target = new HashMap();
            target.put("resourceId", "userTaskStep_" + stepNum);
            childShape.put("target", target);

            return childShape;
        }
        return null;
    }

}
